package com.code.generate;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;

import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;

/**
 * 生成代码
 *
 * @author huang
 * @create 2019-01-12 14:24
 **/

public class Code {


    public static void main(String[] agrs) {
        URL url = Code.class.getClassLoader().getResource("json/trade/taobao.trade.fullinfo.get.json");
        File jsonFile = new File(url.getFile());
        JSONObject dataJson = JSONUtil.readJSONObject(jsonFile, Charset.defaultCharset());
        //获取到需要解析的json
        JSONArray responseParams = (JSONArray) ((JSONObject) dataJson.get("data")).get("responseParams");
        Map<String, String> classInfo = new HashMap<>();
        //最外层类的注释
        classInfo.put("classDocs", "单笔交易的信息");
        //最外层类名
        classInfo.put("className", "TBTradeDetailBO");
        //最外层包名
        classInfo.put("packageName", "com.vma.thrid.jishibao.domain.vo.trades.full");
        searchParams(responseParams, classInfo);
    }

    /**
     * @param responseParams
     */
    public static void searchParams(JSONArray responseParams, Map<String, String> classInfo) {
        List<Map<String, Object>> fields = new ArrayList<>();
        for (Object param : responseParams) {
            JSONObject pa = (JSONObject) param;
            Map<String, Object> field = new HashMap<>();
            JSONArray subParams = (JSONArray) pa.get("subParams");
            //如果存在子属性 则进入递归
            if (subParams != null && subParams.size() > 0) {
                Map<String, String> subClassInfo = new HashMap<>();
                //子属性注释
                subClassInfo.put("classDocs", pa.get("description").toString());
                //子属性类名
                subClassInfo.put("className",
                        "TB" + StrUtil.upperFirst(StrUtil.toCamelCase(pa.get("name").toString())) + "BO");
                //子属性报名
                subClassInfo.put("packageName", classInfo.get("packageName"));
                //进入递归
                searchParams(subParams, subClassInfo);
                field.put("subParams", StrUtil.upperFirst(pa.get("name").toString()));
            }
            //字段类型
            field.put("fieldType", pa.get("type").toString());
            //字段名称 转成小写驼峰
            field.put("fieldName", StrUtil.toCamelCase(pa.get("name").toString()));
            //字段描述
            field.put("fieldNameDocs", pa.get("description"));
            //字段是否必填  在response可以注释掉  request生成是否必填
            //field.put("fieldRequired", pa.get("required"));
            //字段示例
            field.put("demoValue", pa.get("demoValue"));
            fields.add(field);
        }
        //生成代码
        poteGenerate(classInfo, fields);
    }


    /**
     * @param classInfo 类信息
     * @param fieldList 字段信息
     */
    public static void poteGenerate(Map<String, String> classInfo, List<Map<String, Object>> fieldList) {
        //生成类的配置
        TypeSpec.Builder targetBuilder = TypeSpec.classBuilder(
                classInfo.get("className")).addModifiers(Modifier.PUBLIC);
        targetBuilder.addJavadoc(classInfo.get("classDocs"));
        targetBuilder.addAnnotation(ClassName.get("lombok", "Data"));
        //循环生成字段
        for (Map<String, Object> field : fieldList) {
            //类型判断
            Type type = null;
            if (field.get("subParams") != null) {
                type = List.class;
            } else {
                String fieldType = field.get("fieldType").toString();
                if ("Boolean".equals(fieldType)) {
                    type = Boolean.class;
                } else if ("String".equals(fieldType)) {
                    type = String.class;
                } else if ("Date".equals(fieldType)) {
                    type = Date.class;
                } else if ("Number".equals(fieldType)) {
                    type = Long.class;
                } else if ("Json".equals(fieldType)) {
                    type = String.class;
                } else if ("Price".equals(fieldType)) {
                    type = BigDecimal.class;
                } else {
                    System.out.println(fieldType);
                }
            }
            //注释生成
            FieldSpec fieldSpec;
            if (field.get("fieldRequired") != null) {
                fieldSpec = FieldSpec.builder(type, field.get("fieldName").toString(), Modifier.PRIVATE)
                        .addJavadoc("描述:$S\n示例:$S\n是否必填:$S\n",
                                field.get("fieldNameDocs").toString(),
                                field.get("demoValue").toString(),
                                field.get("fieldRequired").toString()).build();
            } else {
                fieldSpec = FieldSpec.builder(type, field.get("fieldName").toString(), Modifier.PRIVATE)
                        .addJavadoc("描述:$S\n示例:$S\n",
                                field.get("fieldNameDocs").toString(),
                                field.get("demoValue").toString()).build();
            }
            targetBuilder.addField(fieldSpec);
        }
        //生成代码
        TypeSpec targetClass = targetBuilder.build();
        JavaFile file = JavaFile.builder(classInfo.get("packageName"), targetClass).build();
        try {
            file.writeTo(System.out);
            String classPath = System.getProperty("user.dir");
            File codeFile = new File(classPath + "\\src\\main\\java\\");
            file.writeTo(codeFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
